#ifndef UnstructMG_CG_HPP
#define UnstructMG_CG_HPP

#include "iter_solver.hpp"

template<typename idx_t, typename pc_data_t, typename pc_calc_t, typename ksp_t, int dof>
class CGSolver : public IterativeSolver<idx_t, pc_data_t, pc_calc_t, ksp_t, dof> {
public:
    CGSolver();
protected:
    // void Pipelined          (const par_Vector<idx_t, ksp_t, dof> & b, par_Vector<idx_t, ksp_t, dof> & x) const;
    // void Chronopoulos_Gear  (const par_Vector<idx_t, ksp_t, dof> & b, par_Vector<idx_t, ksp_t, dof> & x) const;
    void Standard           (const par_Vector<idx_t, ksp_t, dof> & b, par_Vector<idx_t, ksp_t, dof> & x) const;
    // 默认采用Chronopoulos-Gear CG（每迭代步只需一次AllReduce）
    void Mult_ipl(const par_Vector<idx_t, ksp_t, dof> & b, par_Vector<idx_t, ksp_t, dof> & x) const;
};

typedef CGSolver<int, double, double, double, 1> CGSolver_I32All64_DOF1;
typedef CGSolver<int, double, double, double, 2> CGSolver_I32All64_DOF2;
typedef CGSolver<int, double, double, double, 3> CGSolver_I32All64_DOF3;
typedef CGSolver<int, double, double, double, 4> CGSolver_I32All64_DOF4;

typedef CGSolver<int, float , double, double, 1> CGSolver_I32K64P64D32_DOF1;
typedef CGSolver<int, float , double, double, 2> CGSolver_I32K64P64D32_DOF2;
typedef CGSolver<int, float , double, double, 3> CGSolver_I32K64P64D32_DOF3;
typedef CGSolver<int, float , double, double, 4> CGSolver_I32K64P64D32_DOF4;

typedef CGSolver<int, float , float , double, 1> CGSolver_I32K64P32D32_DOF1;
typedef CGSolver<int, float , float , double, 2> CGSolver_I32K64P32D32_DOF2;
typedef CGSolver<int, float , float , double, 3> CGSolver_I32K64P32D32_DOF3;
typedef CGSolver<int, float , float , double, 4> CGSolver_I32K64P32D32_DOF4;

typedef CGSolver<int, float , float , float , 1> CGSolver_I32All32_DOF1;
typedef CGSolver<int, float , float , float , 2> CGSolver_I32All32_DOF2;
typedef CGSolver<int, float , float , float , 3> CGSolver_I32All32_DOF3;
typedef CGSolver<int, float , float , float , 4> CGSolver_I32All32_DOF4;
#ifdef USE_FP16
typedef CGSolver<int, __fp16, float , double, 1> CGSolver_I32K64P32D16_DOF1;
typedef CGSolver<int, __fp16, float , double, 2> CGSolver_I32K64P32D16_DOF2;
typedef CGSolver<int, __fp16, float , double, 3> CGSolver_I32K64P32D16_DOF3;
typedef CGSolver<int, __fp16, float , double, 4> CGSolver_I32K64P32D16_DOF4;

typedef CGSolver<int, __fp16, float , float , 1> CGSolver_I32K32P32D16_DOF1;
typedef CGSolver<int, __fp16, float , float , 2> CGSolver_I32K32P32D16_DOF2;
typedef CGSolver<int, __fp16, float , float , 3> CGSolver_I32K32P32D16_DOF3;
typedef CGSolver<int, __fp16, float , float , 4> CGSolver_I32K32P32D16_DOF4;
#endif

#endif